package com.program.services;

import com.program.controller.MainController;
import com.program.eneity.Airplane;
import com.program.eneity.FlightSchedule;
import com.program.utils.DataProcessing;
import com.program.eneity.Date;
import com.program.utils.LinkQueue;
import com.program.utils.Random;
import javafx.application.Platform;

/**
 * @program: AirportSystem
 * @description: 航班服务
 * @author: 19071027
 * @create: 2021-09-07 19:04
 **/
public class AirplaneService {

    private static AirplaneService airplaneService = null;

    /**
     * 全部航班数目
     */
    private int num;

    /**
     * 入港航班数目
     */
    private int numIn;

    /**
     * 出港航班
     */
    private int numOut;

    /**
     * 第一班航班的时间
     */
    private Date startDate = new Date();

    /**
     * 存放所有航班的数组
     */
    private Airplane[] airplanes;

    /**
     * 航班表
     */
    private FlightSchedule[] flightSchedules;

    /**
     * 所有起飞的飞机
     */
    private LinkQueue takeOffAirplanes = new LinkQueue();

    /**
     * 所有降落的飞机
     */
    private LinkQueue landAirplanes = new LinkQueue();


    private AirplaneService() {
    }

    public static AirplaneService getAirplaneService() {
        if (airplaneService == null) {
            synchronized (AirplaneService.class) {
                if (airplaneService == null) {
                    airplaneService = new AirplaneService();
                }
            }
        }
        return airplaneService;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public int getNumIn() {
        return numIn;
    }

    public void setNumIn(int numIn) {
        this.numIn = numIn;
    }

    public int getNumOut() {
        return numOut;
    }

    public void setNumOut(int numOut) {
        this.numOut = numOut;
    }

    public Date getStartDate() {
        return startDate;
    }

    public void setStartDate(Date firstDate) {
        int newMin = (Integer.valueOf(firstDate.getMinute()) - 10) % 60;
        int newHour = (Integer.valueOf(firstDate.getHour()) + ((Integer.valueOf(firstDate.getMinute()) - 10) / 60)) % 24;
        if (newHour < 10) {
            firstDate.setHour("0" + newHour);
        }
        else {
            firstDate.setHour(String.valueOf(newHour));
        }

        if (newMin < 10) {
            firstDate.setMinute("0" + newMin);
        }
        else {
            firstDate.setMinute(String.valueOf(newMin));
        }

        this.startDate = firstDate;
    }

    public FlightSchedule[] getFlightSchedules() {
        return flightSchedules;
    }

    public void setFlightSchedules(FlightSchedule[] flightSchedules) {
        this.flightSchedules = flightSchedules;
    }

    public Airplane[] getAirplanes() {
        return airplanes;
    }

    public LinkQueue getTakeOffAirplanes() {
        return takeOffAirplanes;
    }

    public LinkQueue getLandAirplanes() {
        return landAirplanes;
    }

    /**
     * 获取所有需要调度的航班信息并封装航班实体
     */
    public void createAirplanes() {
        //航班时刻表数据
        String[] data = DataProcessing.getDataInTxt();

        airplanes = new Airplane[num];

        flightSchedules = new FlightSchedule[num];

        for (int i = 0; i < num; i++) {

            //str[0]:航空公司航班号  str[1]:起飞时间 str[2]:降落时间
            String[] str = data[i].split(",");

            //时间整数数组 [0]:起飞小时 [1]:起飞分钟  [2]:降落小时  [3]:降落分钟
            String[] timeStr = DataProcessing.getTimeData(data[i]);

            //封装起飞时间 若为降落 则为空
            Date departureTime = "0".equals(timeStr[0]) && "0".equals(timeStr[1]) ? null : new Date(timeStr[0], timeStr[1]);
            //封装降落时间
            Date landTime = "0".equals(timeStr[2]) && "0".equals(timeStr[3]) ? null : new Date(timeStr[2], timeStr[3]);

            //获取第一班航班的时间
            if (i == 0) {
                Date firstDate = new Date();
                String hour, min;
                if (departureTime != null) {
                    hour = departureTime.getHour();
                    min = departureTime.getMinute();
                }
                else {
                    hour = landTime.getHour();
                    min = landTime.getMinute();
                }
                firstDate.setHour(hour);
                firstDate.setMinute(min);
                setStartDate(firstDate);
            }

            //获取所属航空公司
            String company = str[0].substring(0, 2);

            //获取航班号
            String id = str[0].substring(2);

            //为降落的飞机随机生成10-100燃油数
            int fuel = 0;

            if (departureTime == null) {
                //降落的飞机
                fuel = Random.getRandom();
            }
            else {
                //起飞的飞机
                fuel = 100;
            }

            //封装航班
            airplanes[i] = new Airplane(company, id, departureTime, landTime, fuel);

            //封装航班表
            flightSchedules[i] = new FlightSchedule(company, id, str[1], str[2]);

        }

    }

    /**
     * 将飞机分成起飞和降落两组
     */
    public void classifyAirplanes() {
        int numI=0;
        int numO=0;
        if (airplanes != null) {
            for (Airplane airplane : airplanes) {
                if (airplane.getDepartureTime() == null) {
                    //    降落
                    landAirplanes.add(airplane);
                    numI++;
                }
                else {
                    //    起飞
                    takeOffAirplanes.add(airplane);
                    numO++;
                }
            }
        }
        setNumIn(numI);
        setNumOut(numO);
    }

    /**
     * 判断是否到达了起飞飞机进入跑道的时间
     *
     * @param date     当前时间
     * @param airplane 最近的一班起飞航班
     * @return true-应该进入跑道 false-不进入跑道
     */
    public boolean isDepartureTime(Date date, Airplane airplane) {
        if (airplane == null) {
            return false;
        }

        int departureTimeHour = Integer.valueOf(airplane.getDepartureTime().getHour());
        int departureTimeMin = Integer.valueOf(airplane.getDepartureTime().getMinute());
        int currentTimeHour = Integer.valueOf(date.getHour());
        int currentTimeMin = Integer.valueOf(date.getMinute());

        if (departureTimeHour == currentTimeHour && departureTimeMin == currentTimeMin) {
            return true;
        }else if (departureTimeHour == currentTimeHour && departureTimeMin < currentTimeMin){
            return true;
        }else if (departureTimeHour < currentTimeHour && departureTimeMin > currentTimeMin){
            return true;
        }

        return false;

    }

    /**
     * 判断最近的一架着陆飞机是否到达
     *
     * @param date     当前时间
     * @param airplane 最近的一架着陆飞机
     * @return true-到达 false-未到达
     */
    public boolean isLandingTime(Date date, Airplane airplane) {
        if (airplane == null || airplane.getLandingTime() == null) {
            return false;
        }

        int landingTimeHour = Integer.valueOf(airplane.getLandingTime().getHour());
        int landingTimeMin = Integer.valueOf(airplane.getLandingTime().getMinute());
        int currentTimeHour = Integer.valueOf(date.getHour());
        int currentTimeMin = Integer.valueOf(date.getMinute());

        if (landingTimeHour == currentTimeHour && landingTimeMin == currentTimeMin) {
            return true;
        }else if (landingTimeHour == currentTimeHour && landingTimeMin < currentTimeMin){
            return true;
        }else if (landingTimeHour < currentTimeHour && landingTimeMin > currentTimeMin){
            return true;
        }

        return false;
    }

    /**
     * 构造等待队列
     */
    public void createWaitingQueue() {

        Airplane takeOffAirplane = (Airplane) MainController.takeOffAirplanes.peek();
        Airplane landingAirplane = (Airplane) MainController.landAirplanes.peek();

        //将飞机加入着陆队列
        if (!MainController.landingWaiting.isFull()) {
            //    有着陆飞机到达
            do {
                if (MainController.landingWaiting.offer(landingAirplane)) {
                    //着陆队列未满
                    landAirplanes.remove();
                    Airplane airplane = landingAirplane;
                    Platform.runLater(new Runnable() {
                        @Override
                        public void run() {
                            if (airplane != null) {
                                MainController.landList.add(airplane.toString());
                            }
                        }
                    });

                    landingAirplane = (Airplane) landAirplanes.peek();
                }
                else {
                    //    着陆队列已满
                    break;
                }
            } while (!MainController.landingWaiting.isFull());

        }

        //将飞机加入起飞队列
        if (!MainController.takeOffWaiting.isFull()) {
            //    当前航班应该进入跑道进行起飞
            do {
                if (MainController.takeOffWaiting.offer(takeOffAirplane)) {
                    //起飞队列未满
                    Airplane airplane = takeOffAirplane;
                    Platform.runLater(new Runnable() {
                        @Override
                        public void run() {
                            if (airplane != null) {
                                MainController.offList.add(airplane.toString());
                            }
                        }
                    });
                    takeOffAirplanes.remove();
                    takeOffAirplane = (Airplane) takeOffAirplanes.peek();
                }
                else {
                    //    起飞队列已满
                    break;
                }
            } while (!MainController.takeOffWaiting.isFull());

        }
    }

    /**
     * 构造优先级队列
     */
    public void createPriorityQueue() {
        //将当前时间点起飞或着陆的飞机加入优先级队列
        while (airplaneService.isDepartureTime(MainController.date, MainController.takeOffWaiting.peek()) || airplaneService.isLandingTime(MainController.date, MainController.landingWaiting.peek())) {
            if (airplaneService.isDepartureTime(MainController.date, MainController.takeOffWaiting.peek())) {
                //    当前时间点起飞的飞机
                MainController.offPriorityQueue.offer(MainController.takeOffWaiting.remove());
                Platform.runLater(new Runnable() {
                    @Override
                    public void run() {
                        if (MainController.offList.size()!=0){
                            MainController.offList.remove(0);
                        }
                    }
                });
                if (MainController.offPriorityQueue.isFull()){
                    break;
                }

            }
            if (airplaneService.isLandingTime(MainController.date, MainController.landingWaiting.peek())) {
                //    当前时间点着陆的飞机
                Platform.runLater(new Runnable() {
                    @Override
                    public void run() {
                        if (MainController.landList.size()!=0){
                            MainController.landList.remove(0);
                        }
                    }
                });
                MainController.landPriorityQueue.add(MainController.landingWaiting.remove());
                if (MainController.landPriorityQueue.isFull()){
                    break;
                }
            }
        }
    }

}
